Skip to content

Fenrir fixes#10968

Open
Frauschi wants to merge 8 commits into
wolfSSL:masterfrom
Frauschi:fenrir_tls
Open

Fenrir fixes#10968
Frauschi wants to merge 8 commits into
wolfSSL:masterfrom
Frauschi:fenrir_tls

Conversation

@Frauschi

Copy link
Copy Markdown
Contributor

Summary

This branch collects a set of security-hardening and RFC-conformance fixes that a Fenrir security review surfaced across wolfCrypt (ASN.1 / attribute certificates, ECC), the TLS and DTLS 1.3 stacks, the OpenSSL compatibility layer, and the sniffer. It also documents three intentional, off-by-default build knobs whose RFC non-conformance was previously undocumented.

Behavioral fixes

Area Change Reference
wolfCrypt ECC wolfSSL_ECDSA_do_verify returned success (fail-open) in the WOLF_CRYPTO_CB_ONLY_ECC path when i2d_ECDSA_SIG failed to encode the signature. It now maps the encoding failure to WOLFSSL_FATAL_ERROR so an error is never reported as a valid signature. F-6981
wolfCrypt attribute certs VerifyX509Acert (and therefore wc_VerifyX509Acert / wolfSSL_X509_ACERT_verify) never checked the certificate validity period, so an expired or not-yet-valid attribute certificate verified successfully. It now enforces notBefore / notAfter via CheckDate. Also corrects ParseX509Acert to report ASN_AFTER_DATE_E instead of ASN_BEFORE_DATE_E on a failed notAfter check. RFC 5755 5.4, F-6986
Sniffer The session, server, and keylog-secret hash tables elided all locking whenever HAVE_C___ATOMIC was defined, on the assumption the tables are thread-local. Thread-locality is actually governed by THREAD_LS_T, so a build with HAVE_C___ATOMIC and NO_THREAD_LS left the tables as process-shared globals with no synchronization (data race plus use-after-free during renegotiation). Lock elision is now gated on real thread-local storage. F-6983
TLS 1.2 / 1.3 The default signature_algorithms list advertised and accepted the SHA-1 schemes rsa_pkcs1_sha1 and ecdsa_sha1 for TLS 1.2 and later, based only on build flags. They are now offered only for TLS 1.0 / 1.1 handshakes unless WOLFSSL_ALLOW_TLS_SHA1 is defined. RFC 9155, RFC 8446 4.2.3, F-6991
TLS secure renegotiation The SecureRenegotiation extension embeds a Keys tmp_keys copy of the session cipher and MAC keys used for the renegotiated epoch. It was freed with a bare XFREE, leaving key material in freed heap. It is now wiped with ForceZero before free, matching the ssl->keys teardown. F-7008
DTLS 1.3 Receiving an EndOfEarlyData message did not send the required unexpected_message fatal alert; the connection was dropped silently. Dtls13CheckEpoch now sends the alert, and the DTLS 1.3 handshake dispatch in DoProcessReplyEx now calls SendFatalAlertOnly on error, mirroring the DTLS 1.2 path so other handshake errors are reported rather than dropped silently. RFC 9147 5.6.1, F-6987

Documentation (intentional opt-in behaviour, no code change)

Area Change Reference
ALPN WOLFSSL_ALPN_CONTINUE_ON_MISMATCH makes a server continue without an agreed protocol on mismatch, like OpenSSL, instead of sending the no_application_protocol alert. This is an explicit, caller-selected opt-in (wolfSSL_UseALPN rejects a call that sets neither mismatch option). The RFC non-conformance is now documented at the option enum, the wolfSSL_UseALPN parameter docs, and the ALPN_find_match enforcement site. RFC 7301 3.2, F-7003
Certificate validation ALLOW_INVALID_CERTSIGN and IGNORE_KEY_EXTENSIONS are off-by-default, RFC-non-conformant escape hatches for interop with deployed certificates that carry malformed key usage. Their scope and intent are now documented at the asn.c macro list and each enforcement site. F-6984, F-6985

Testing

New and extended regression tests:

  • tests/api/test_ossl_x509_acert.c - extends test_wolfSSL_X509_ACERT_verify to install a wc_SetTimeCb that moves the clock past the test certificate's notAfter, then asserts verification fails. Fails before the attribute-certificate fix, passes after.
  • tests/api.c - extends test_wolfSSL_sigalg_info to assert the signature_algorithms list contains no SHA-1 scheme for TLS 1.2 and TLS 1.3 (tls1_2 set), and still contains them for TLS 1.0 / 1.1 when compiled in. Fails before the SHA-1 gating fix, passes after.
  • tests/api/test_dtls13.c - extends test_dtls13_epochs to assert a fatal unexpected_message alert is recorded after Dtls13CheckEpoch(ssl, end_of_early_data). Fails before the DTLS 1.3 fix, passes after.

Fixes without a dedicated test, with rationale:

  • ECDSA fail-open: the branch only compiles under WOLF_CRYPTO_CB_ONLY_ECC and needs fault injection to force an encoding failure. Verified by compiling that configuration (with a negative-control syntax error to prove the branch is built) and running the ECC and OpenSSL-compat EC suites.
  • Sniffer locking: a compile-time locking-guard defect that only manifests as a race under a specific build combination with concurrent threads. Verified by building both configurations, confirming via the preprocessor that the mutex path is engaged under NO_THREAD_LS, and running scripts/sniffer-testsuite.test in both.
  • Secure-renegotiation zeroize: zeroization before free is not reliably observable from a unit test. Verified by building --enable-secure-renegotiation with AddressSanitizer and confirming the free path runs cleanly (0 sanitizer reports) across the secure-renegotiation tests.

All changes verified by building the affected feature configuration, running the touched suite (full API suite reports 0 failures in each configuration), and restoring the working configuration afterward.

Frauschi added 8 commits July 22, 2026 13:07
…nal opt-in knobs

These compile-time flags are off by default and RFC-non-conformant when
enabled. Document their scope and intent at the asn.c macro list and each
enforcement site (ParseCertRelative, VerifyCRL_Signature, AddCA,
ProcessPeerCerts) so their opt-in nature is clear. No behavior change.

Fixes F-6984 and F-6985.
In the WOLF_CRYPTO_CB_ONLY_ECC path of wolfSSL_ECDSA_do_verify, a
non-positive length from i2d_ECDSA_SIG (an encoding failure) skipped
the verify block and left ret at its initial value of 1, reporting a
valid signature although no verification was performed. Map the
encoding failure to WOLFSSL_FATAL_ERROR so it is not treated as a
successful verification.

Fixes F-6981.
VerifyX509Acert parsed the acert and checked the signature but never
validated the notBefore and notAfter dates, so wolfSSL_X509_ACERT_verify
and wc_VerifyX509Acert accepted expired or not-yet-valid attribute
certificates whenever the signature was good. Call CheckDate for both
validity bounds before signature verification. CheckDate returns the
proper date error and honors the runtime skip-date control. Also correct
ParseX509Acert to report ASN_AFTER_DATE_E instead of ASN_BEFORE_DATE_E
when the notAfter date check fails.

Fixes F-6986.
The sniffer elided all session, server, and keylog secret list locking
whenever HAVE_C___ATOMIC was defined, assuming those tables are
thread-local and need no mutex. Thread-locality is actually governed by
THREAD_LS_T, which is only a real qualifier when HAVE_THREAD_LS is set
and NO_THREAD_LS is not. A build with HAVE_C___ATOMIC and NO_THREAD_LS
left the tables as process-shared globals with no synchronization, so
concurrent packet processing raced on the list pointers and could free a
session another thread was still using. Gate the lock elision on both the
atomic fast path and real thread-local storage, and take the mutexes
whenever the tables are process-shared. The stats counter path is
unchanged because it uses a genuine atomic add.

Fixes F-6983.
InitSuitesHashSigAlgo added the ecdsa_sha1 and rsa_pkcs1_sha1 signature
schemes to the signature_algorithms list based only on the build flags,
ignoring the negotiated protocol version. Because that list is also the
set a peer's signatures are validated against, any build with old TLS
compiled in advertised and accepted SHA-1 handshake and certificate
signatures for TLS 1.2, which RFC 9155 deprecates. Gate the SHA-1 schemes
on the negotiated version so they are offered only for TLS 1.0 and 1.1
handshakes, unless WOLFSSL_ALLOW_TLS_SHA1 is defined to opt back in. The
same gate excludes them for TLS 1.3, as required by RFC 8446.

Fixes F-6991.
The SecureRenegotiation extension embeds a Keys tmp_keys copy of the
session cipher and MAC keys, which are the keys used for the renegotiated
epoch. SCR_FREE_ALL freed that struct with a bare XFREE, leaving a full
set of session keys intact in freed heap memory. Wipe the struct with
ForceZero before freeing it, matching the ForceZero of ssl->keys on
connection teardown.

Fixes F-7008.
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH makes a server continue the handshake
without an agreed protocol when no ALPN protocol matches, like OpenSSL,
instead of sending the fatal no_application_protocol alert that RFC 7301
section 3.2 requires. This is an explicit, caller-selected opt-in:
wolfSSL_UseALPN rejects a call that sets neither mismatch option, and the
library never enables it implicitly. Document the RFC non-compliance at
the option enum, the wolfSSL_UseALPN options parameter, and the mismatch
handling in ALPN_find_match so the trade-off is clear at every point a
user or maintainer encounters it. No behavior change.

Fixes F-7003.
RFC 9147 section 5.6.1 states that EndOfEarlyData is not used in DTLS 1.3
and that a receiver must terminate the connection with an
unexpected_message alert. Dtls13CheckEpoch grouped end_of_early_data into
the default case that returns SANITY_MSG_E without sending any alert, and
the DTLS 1.3 handshake dispatch in DoProcessReplyEx did not send a fatal
alert on error the way the DTLS 1.2 path does, so the connection was
dropped silently. Add an explicit end_of_early_data case that sends the
unexpected_message alert, and mirror the DTLS 1.2 SendFatalAlertOnly
handling in the DTLS 1.3 dispatch so other handshake errors are also
reported rather than dropped silently.

Fixes F-6987.
@Frauschi Frauschi self-assigned this Jul 22, 2026
@github-actions

Copy link
Copy Markdown

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #10968

Scan targets checked: wolfcrypt-bugs, wolfcrypt-rs-bugs, wolfcrypt-src, wolfssl-bugs, wolfssl-src

No new issues found in the changed files. ✅

@Frauschi Frauschi assigned wolfSSL-Bot and unassigned Frauschi Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants